<?php
class DB {

	const LOCAL					= 18;

	private $table  			= null;
	private $i18n 				= null;
	private $connection			= null;
	private $hash 				= array();
	private $sql				= null;
	private $local 				= false;
	private $find 				= false;
	private $className			= null;

	private $where				= null;
	private $order				= null;
	private $offset 			= null;
	private $limit 				= null;

	public function __construct($table, $local = null) {

		$this->className = $table;

		$config = new Config;

		if (in_array($table, $config->dbTables) === false) {
			return;
		}

		foreach ($config->dbTables as $k => $v) {
			if ($v == $table) {
				$table = $k;
				break;
			}
		}

		$this->table = sprintf("%s%s", $config->dbPrefix, $table);
		$this->i18n = I18n::getInstance();
		$this->i18n->addFile("i18n/%LOCAL/framework/model.xml");

		$this->connection = new DBDriver($config->dbHost, $config->dbUser, $config->dbPass, $config->dbName);
		if ($this->connection === false) {
			$error = $this->i18n->getText("connection_failed", $config->dbName, $config->dbHost);
			Log::write($error);
		}

		if ($local === Model::LOCAL) {
			$this->local = $config->local;
		}

	}

	public function __destruct() {
		$this->connection->dbFreeMemory($this->connection);
		if ($this->connection) {
			$this->connection->dbClose($this->connection);
		}
        $this->connection = null;
    }

	public function find($array = null) {

		if (is_string($array) === true) {
			return $this->execute($array);
		}

		$this->find = $array;
		$where = array();
		if ($array == null) return;
		foreach ($array as $key => $value) {
			if ($value === null) continue;
			$sqlOperation = (is_numeric(strpos($value, "%"))) ? "LIKE" : "=";
			$where[] = sprintf("`%s` %s %s", $key, $sqlOperation, $this->escapeString($value));
		}
		$this->where = $where;
		unset($where);
	}

	public function offset($offset) {
		$this->offset = (int) $offset;
	}

	public function limit($limit) {
		$this->limit = (int) $limit;
	}

	public function order($field, $type = "DESC") {
		$this->order[0] = $this->escapeString($field, "`");
    	$this->order[1] = (strtolower($type) == "desc") ? "DESC" : "ASC";
	}

	public function execute($query = null) {
		if (($query == null) || ($query == "*")) {

			$select				= null;
			$where				= null;
			$local				= null;
			$limit				= null;
			$order				= null;
			$sqlConditional		= "WHERE";

			if (($this->find == false) || ($query == "*")) {
				$select = sprintf("SELECT * FROM %s", $this->table);
			} else {
				$hash	= array_map(array($this, "quoteHash"), array_keys($this->find));
				$keys	= implode(", ", $hash);
				$select = sprintf("SELECT %s FROM %s", $keys, $this->table);
			}
	
			if ($this->find != false) {
				foreach ($this->where as $condition) {
					$where[] = sprintf("%s %s", $sqlConditional, $condition);
					$sqlConditional = "AND";
				}
				$where = (is_array($where)) ? implode(" ", $where) : null;	
			}
			
			if ($this->local != false) {
				$local = sprintf('%s local = "%s"', $SqlConditional, $this->local);
				$SqlConditional = "AND";
			}

			if (is_int($this->offset)) {
				$limit = sprintf("LIMIT %d, %d", (int) $this->offset, (int) $this->limit);
			}
	
			if (is_array($this->order)) {
				$order = sprintf("ORDER BY %s %s", $this->order[0], $this->order[1]);
			}
	
			$this->sql = sprintf("%s %s %s %s %s", $select, $where, $local, $order, $limit);

		} else {
			$this->sql = sprintf($query, $this->table);
		}


		Log::write($this->sql);

		if ($this->connection->dbQuery($this->sql) === false) {
			return false;
		}
	
		$result = array();
		$i = 0;
		while ($row = $this->connection->dbObject()) {
			$result[$i] = new $this->className;
			foreach ($row as $key => $value) {
				$result[$i]->{$key} = $value;
			}
			$i++;
		}

		unset($this);
		return $result;
	}

	private function escapeString($value, $char = '"') {
		if (is_numeric($value)) {
			return sprintf('%s%s%s', $char, $this->connection->dbEscapeString($value), $char);
		} else {
			return sprintf('%s%s%s', $char, $this->connection->dbEscapeString($value), $char);
		}
	}

	public function quoteHash($value) {
		return sprintf("`%s`", $value);
	}

}